package flib;

import java.util.Collections;
import java.util.HashMap;
import java.util.Vector;

import processing.core.PApplet;
import simpleGeom.Vec2D;
import simpleGeom.Vec3D;

public class MarkovLearn extends PApplet{
Vector<Vec2D>points=new Vector<Vec2D>();
Vector<Vec2D>points2=new Vector<Vec2D>();
Vector<Vector<Float>>angles=new Vector<Vector<Float>>();
int nAngles=32;

float maxL=20;
float maxA=PI*2f;
float dAngle=maxA/nAngles;
HashMap<Float,Vector<Float>>deltaAngles;
public void setup(){
	size(800,800);
	rectMode(CENTER);
}

public void draw(){
	background(0);
	if (flagInit){
		initFile();
		flagInit=false;
	}
	if (mousePressed&&frameCount%2==0){
		Vec2D newP=new Vec2D(mouseX,mouseY);
		if (points.size()==0){
			points.add(newP);
		}
		else{
			Vec2D oldP=points.lastElement();
			Vec2D v=Vec2D.sub(newP, oldP);
			float l=v.mag();
			if (l>maxL){
				int nP=(int)(l/maxL)+1;
				v.normalize();
				float cD=l/nP;
				for (int i=1;i<=nP;i++){
					Vec2D cV=Vec2D.mult(v, i*cD);
					cV.add(oldP);
					points.add(cV);
				}
			}
		}
		//points.add(new Vec2D(mouseX,mouseY));
		
	}
	stroke(255);
	display(points);
	stroke(255,0,0);
	display(points2);
}
public void initFile(){
	println("points.sze"+points.size());
	angles=new Vector<Vector<Float>>();
	
	for (int i=0;i<nAngles;i++){
		Vector<Float> angleR=new Vector<Float>();
		//Float f=new Float(i*maxA/nAngles);
		
		
		//angleR.add(new Float(0));
		//angleR.add(new Float(random(maxA)));
		//angleR.add(f);
		angles.add(angleR);
	}
	float lastDeltaAngle=0;
	for (int i=0;i<points.size()-2;i++){
		Vec2D v1=points.get(i);
		Vec2D v2=points.get(i+1);
		Vec2D v3=points.get(i+2);
		Vec2D v12=Vec2D.sub(v2, v1);
		Vec2D v23=Vec2D.sub(v3, v2);
		float a1=Vec2D.getTheta(v12);
		
		//if (a1<0)a1=maxA+a1;
		float a2=Vec2D.getTheta(v23);
		//if (a2<0)a2=maxA+a2;
		
		float dAngle=a2-a1;
		dAngle=(float) Vec2D.getAngleBetweenCCW(a1, a2);
		println("dAngle: "+dAngle);
		if (dAngle<0)dAngle=maxA+dAngle;
		//dAngles.add(dAngle);
		//println("Angle: "+a1);
		
		Vector<Float> angleR=getAngleTable(lastDeltaAngle);
		dAngle=getRoundedAngle(dAngle);
	
		angleR.add(dAngle);
		lastDeltaAngle=dAngle;
		//angleR.add(a2+dAngle);
		//angleR.add(a2-dAngle);
		
		
	}
	copy(100);
}


public void display(Vector<Vec2D> points){
	for (int i=0;i<points.size()-1;i++){
		Vec2D v1=points.get(i);
		rect(v1.x,v1.y,2,2);
		Vec2D v2=points.get(i+1);
		line(v1.x,v1.y,v2.x,v2.y);
	}
}

public float getNextAngle(float l){
	Vector<Float> angleR=getAngleTable(l);
	if (angleR.size()==0)return 0;
	Collections.shuffle(angleR);
	return angleR.get(0);
}


public void copy(int n){
	points2=new Vector<Vec2D>();
	points2.add(new Vec2D(width*0.5f,height*0.5f));
	points2.add(new Vec2D(width*0.5f+maxL,height*0.5f));
	float lastAngle=0;
	float lastDelta=0;
	float lastX=width*0.5f;
	float lastY=height*0.5f;
	float lastL=maxL;
	for (int i=0;i<n;i++){
		
		lastAngle+=lastDelta;
		lastDelta=getNextAngle(lastDelta);
		
		Vec2D newPos=Vec2D.getPolar(lastAngle,lastL);
		lastX+=newPos.x;
		lastY+=newPos.y;
		points2.add(new Vec2D(lastX,lastY));
	}
}

float getRoundedAngle(float angle){
	if (angle>=maxA)angle=angle%maxA;
	int iAngle=Math.round(angle/dAngle);
	//if (iAngle==nAngles)iAngle=0;
	return iAngle*dAngle;
}

Vector<Float> getAngleTable(float angle){
	if (angle>=maxA)angle=angle%maxA;
	
	int cI= Math.round((angle*nAngles/maxA));
	//if (cI>=angles.size())return angles.get(0);
	return angles.get(cI);
	
	//return angles.get(cI);
}

boolean flagInit;
public void keyPressed(){
	if (key=='s'){
		flagInit=true;
	}
}
public void mousePressed(){
	points=new Vector<Vec2D>();
	
}

}
